作用域链
当代码在一个环境中执行时,会创建一个**作用域链对象(scope chain)**。
作用域链的首位,始终是当前执行环境的变量对象。这是一个包含 arguments 和其它命名参数值的活动对象。第二位是外部函数的活动对象,第三位是外部函数的外部函数的活动对象,......,直到作为作用域终点的全局执行环境。
var name = "zhar";
function say(){
var age = 30;
console.log(name+"-"+age+"-"+address);// 错误:address is not defined
function info(){
var address = "北京";
console.log(name+"-"+age+"-"+address);//zhar-30-北京
}
info()
}
say();//
console.log(name+"-"+age+"-"+address);// 错误:age is not defined
这段代码共有三个执行环境:全局环境(window)、say()局部环境、info()局部环境。
在全局环境中有一个变量 name 和一个函数say,在say中有一个变量age和一个函数info,在info中有一个变量address。通过报错信息可以看到,say中可以访问到当前环境中的age及全局环境中的name,info可以访问到当前环境中的address、say环境中的age、全局环境中的name,而在window环境中则只可以访问到name。
可以得出:内部环境可以通过作用域链访问到所有的外部环境,但外部环境不能访问内部环境中的任何变量或函数。
作用域链是有层级、线性的;
*JS 在查找变量时,在当前环境查找到变量便停止继续向上搜索*
var name = 'zhar';
function say(){
var name = 'tom';
console.log(name);//tom
}
say();
console.log(name);//zhar
作用域链示意图:

没有块级作用域
在 JS 中并没有像强类型语言中的块级作用域,比如在JAVA中一对花括号中,是一个块级的作用域
var name = 'zhar'
if(true){
var name = 'tom';
}
console.log(name);
//按着上面作用域链中描述的情况,name应该输出为zhar,但实际情况为tom,便是因为在JS中没有块级作用域的概念
//另外一种块级作用域的典型情况为for循环
for(var i=0;i<5;i++){
//dosomething
}
console.log(i);//5
```